#include <dshow.h>
#include <windows.h>
#include <streams.h>
#include <initguid.h>
#if (1100 > _MSC_VER)
#include <olectrlid.h>
#else
#include <olectl.h>
#endif
#include <math.h>
#include <limits.h>
#include "filguid.h"
#include "Filter.h"
#include "pi.h"
#include "resource.h"

/*Common to All*/
#define TEST MessageBox(0,"Test","TestWindow",0)

const AMOVIESETUP_MEDIATYPE filPinTypes={
	&MEDIATYPE_Video,
	&MEDIASUBTYPE_NULL
};
const AMOVIESETUP_MEDIATYPE filPinTypesa={
	&MEDIATYPE_Audio,
	&MEDIASUBTYPE_NULL
};
const AMOVIESETUP_PIN filPinsa[]=
{
	{
		L"Input",
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypesa
	}
	,
	{
		L"Output",
		FALSE,
		TRUE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypesa
	}
	

};
const AMOVIESETUP_PIN filPins[]=
{
	{
		L"Input",
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypes
	},
	{
		L"Output",
		FALSE,
		TRUE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypes
	}
};
const AMOVIESETUP_FILTER filFiltera=
{
	&CLSID_AuFilter,
	L"AuFilter",
	MERIT_DO_NOT_USE,
	2,
	filPinsa
};
const AMOVIESETUP_FILTER filFilter=
{
	&CLSID_Filter,
	L"Filter",
	MERIT_DO_NOT_USE,
	2,
	filPins
};

CFactoryTemplate g_Templates[]=
{
	{
		L"Filter",
		&CLSID_Filter,
		Filter::CreateInstance,
		NULL,
		&filFilter
	},
	{
		L"FilterProperties",
		&CLSID_FilterPropertyPage,
		FilterProp::CreateInstance,
	},
	{
		L"AuFilter",
		&CLSID_AuFilter,
		AuFilter::CreateInstance,
		NULL,
		&filFiltera
	}
};

int g_cTemplates=sizeof(g_Templates)/sizeof(g_Templates[0]);

#ifdef __cplusplus
extern "C"{
#endif

STDAPI DllRegisterServer()
{
	return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
	return AMovieDllRegisterServer2(FALSE);
}
#ifdef __cplusplus
}
#endif
/**********************Audio Effect Starting*********************/

AuFilter::AuFilter(TCHAR *tzname,LPUNKNOWN punk,HRESULT *hr):
//CBaseRenderer(CLSID_AuFilter,tzname,punk,hr)
CTransInPlaceFilter(tzname,punk,CLSID_AuFilter,hr,TRUE)
{
	mod=NULL;

}
CUnknown* AuFilter::CreateInstance(LPUNKNOWN punk,HRESULT*hr)
{
	AuFilter*pObject=new AuFilter(NAME("AuFilter"),punk,hr);
	if(pObject==NULL)
	{
		*hr=E_OUTOFMEMORY;
	}
	return pObject;

}
HRESULT AuFilter::NonDelegatingQueryInterface(REFIID riid,void **ppv)
{
	if(riid==IID_AuFilter)
	{
		return GetInterface((IAuFilter*)this,ppv);
	}
	else
	//return CBaseRenderer::NonDelegatingQueryInterface(riid,ppv);
	return CTransInPlaceFilter::NonDelegatingQueryInterface(riid,ppv);
}
HRESULT AuFilter::CheckInputType(const CMediaType *pmtin)
{
	WAVEFORMATEX*wfe=(WAVEFORMATEX*)pmtin->pbFormat;

	if(pmtin->majortype!=MEDIATYPE_Audio)
		return VFW_E_TYPE_NOT_ACCEPTED;

	if(pmtin->formattype!=FORMAT_WaveFormatEx)
		return VFW_E_TYPE_NOT_ACCEPTED;

	if(wfe->wFormatTag !=WAVE_FORMAT_PCM)
		return VFW_E_TYPE_NOT_ACCEPTED;
	
	if(mod)
	{
		//mod->bps=wfe->wBitsPerSample;
		//mod->nch=wfe->nChannels;
		//mod->srate=wfe->nSamplesPerSec;
		wf=*wfe;
		mod->open(wf.wBitsPerSample,wf.nChannels,wf.nSamplesPerSec);
		
	}
	return NOERROR;
}

//HRESULT AuFilter::DoRenderSample(IMediaSample*pSample)
HRESULT AuFilter::Transform(IMediaSample *pSample)
{
    BYTE *samples;
	pSample->GetPointer(&samples);
	
	if(mod)
	{
	//	mod->samples=samples;
	//	mod->numsamples=pSample->GetActualDataLength();
		mod->write(samples,pSample->GetActualDataLength(),wf.wBitsPerSample,wf.nChannels,wf.nSamplesPerSec);
	}
	
	return NOERROR;
}
/*HRESULT AuFilter::BeginFlush(void)
{
	mod->flush();
	return CBaseRenderer::BeginFlush();
}
*/

STDMETHODIMP AuFilter::SetDspfunction(AuSample*modt)
{
	mod=modt;
	return NOERROR;
}
STDMETHODIMP AuFilter::SetStop()
{
	if(mod)
		mod->close();
	mod=NULL;
	return NOERROR;
}

/****************End of Audio Effect**********************/
/****************Start of Image Effect********************/

Filter::Filter(TCHAR *tzname,
			   LPUNKNOWN punk,
			   HRESULT *hr):
CTransInPlaceFilter(tzname,punk,CLSID_Filter,hr)
//CPersistStream(punk,hr)
{
	T=0.0;
	opt=0;
	t=0;
	opts=0;
	eopt=0;
	img=NULL;
}
STDMETHODIMP Filter::SetConfigure(HWND hwnd)
{
	img->Configure(hwnd);
	return NOERROR;
}
STDMETHODIMP Filter::SetExtEff(char *fname)
{
	if(fname!=NULL)
	{
		if(img)
			img->Quit(); 
		img=NULL;
		FreeLibrary(hmod);
		hmod=NULL;
		hmod=LoadLibrary(fname);
		Init=NULL;
		Init=(INIT)GetProcAddress(hmod,"Getplugin");
		if(Init)
			img=Init();
		if(img)
			img->Init();
		Init=NULL;
		
	
	}
	return NOERROR;
}
STDMETHODIMP Filter::SetStop()
{
	if(img)
	{
		img->Quit();
		img=NULL;
	}
	FreeLibrary(hmod);
	hmod=NULL;
	return NOERROR;
}
STDMETHODIMP Filter::SetExtEff(int teopt)
{
	eopt=teopt;
	return NOERROR;
}
STDMETHODIMP Filter::SetOptions(int topt)
{
	opt=topt;
	return NOERROR;
}
STDMETHODIMP Filter::SetSmooth(int topts)
{
	opts=topts;
	return NOERROR;
}
CUnknown* Filter::CreateInstance(LPUNKNOWN punk,HRESULT *phr)
{
	Filter *pObject= new Filter(NAME("Filter"),punk,phr);
	if(pObject==NULL)
	{
		*phr=E_OUTOFMEMORY;
	}
	return pObject;
}

HRESULT Filter::CheckInputType(const CMediaType*pmtin)
{
	if(pmtin->majortype!=MEDIATYPE_Video)
	{
		return S_FALSE;
	}
	else
	{
		if(pmtin->subtype==MEDIASUBTYPE_RGB24)
			return S_OK;
		return S_FALSE;
	}
}
HRESULT Filter::Transform(IMediaSample*pSample)
{
	AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
    VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;

	BYTE *pData;                // Pointer to the actual image buffer
    long lDataLen;              // Holds length of any given sample
    int ix;
	int iy;

	RGBTRIPLE *prgb,*prgbr;			// Holds a pointer to the current pixel
	
    pSample->GetPointer(&pData);
    lDataLen = pSample->GetSize();

    // Get the image properties from the BITMAPINFOHEADER

    const int cxImage    = pvi->bmiHeader.biWidth;
    const int cyImage    = pvi->bmiHeader.biHeight;
    int numPixels  = cxImage * cyImage;

	prgb = (RGBTRIPLE*) pData;
	const RGBTRIPLE *top=prgb;
	top++;
	prgbr=(RGBTRIPLE*)pData+(numPixels-1);

	if(opts)
		Smooth(top,cxImage,cyImage);
	
	switch(opt)
	{
	case 1:
		//Invert
		for(iy=0;iy<cyImage;iy++)
		{
			for(ix=0;ix<cxImage;ix++,prgb++)
			{
				prgb->rgbtRed=~prgb->rgbtRed;
				prgb->rgbtBlue=~prgb->rgbtBlue;
				prgb->rgbtGreen=~prgb->rgbtGreen;
			}
		}
		break;
	case 2:
		//Double Lines
		{
			RGBTRIPLE temprgb;
			for (iy=0; iy < cyImage-1; iy++)
			{
				prgbr=prgb+cxImage;
				for(ix=0;ix < cxImage/2;ix+=2,prgb+=2,prgbr-=2)
				{
					temprgb=*prgb;
					*prgb=*prgbr;
					*prgbr=temprgb;
				}
			prgb+=cxImage/2;
			}
			
		}
		break;
	case 3:
		//Gray
		{
			BYTE grey;
			for (iy=0; iy < numPixels-2; iy++, prgb++,prgbr--)
			{
				grey = (30*prgb->rgbtRed + 59*prgb->rgbtGreen+11*prgb->rgbtBlue)/100;
				prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) grey;
			}
		}
		break;
	case 4:
		//Yellow Wash
		for (iy=0; iy < numPixels-2; iy++, prgb++,prgbr--)
		{
			prgb->rgbtRed   = (BYTE) (~prgb->rgbtRed);
			prgb->rgbtGreen = (BYTE) (~prgb->rgbtGreen);
			prgb->rgbtBlue  = (BYTE) (prgb->rgbtBlue);
		}
		break;
	case 5:
		//XRAY
		{
			BYTE grey;
			for (iy=0; iy < numPixels-2; iy++, prgb++,prgbr--)
			{
				grey = (30*prgb->rgbtRed + 59*prgb->rgbtGreen+11*prgb->rgbtBlue)/100;
				prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) grey;
				prgb->rgbtRed   = (BYTE) (~prgb->rgbtRed);
				prgb->rgbtGreen = (BYTE) (~prgb->rgbtGreen);
				prgb->rgbtBlue  = (BYTE) (~prgb->rgbtBlue);
			}
		}
		break;
	case 6:
		//Mirror
		{
			RGBTRIPLE temprgb;
			for (iy=0; iy < cyImage-1; iy++)
			{
				prgbr=prgb+cxImage;
				for(ix=0;ix < cxImage/2;ix++,prgb++,prgbr--)
				{
					temprgb=*prgb;
					*prgb=*prgbr;
					*prgbr=temprgb;
				}
				prgb+=cxImage/2;
			}
		}
		break;
	case 7:
		//CrossOver
		{
			RGBTRIPLE temprgb;
			for (iy=0; iy < cyImage-1; iy++)
			{
				prgbr=prgb+cxImage/2;
				for(ix=0;ix < cxImage/4;ix++,prgb++,prgbr++)
				{
					temprgb=*prgb;
					*prgb=*prgbr;
					*prgbr=temprgb;
				}
				prgb=prgbr+(cxImage/4)-1;
			}
		}
		break;
	case 8:
		//Four Way
		{
			RGBTRIPLE temprgb;
			for (iy=0; iy < cyImage-1; iy++)
			{
				prgbr=prgb+cxImage/2;
				for(ix=0;ix < cxImage/4;ix++,prgb++,prgbr++)
				{
					temprgb=*prgb;
					*prgb=*prgbr;
					*prgbr=temprgb;
				}
				prgb=prgbr+cxImage/4;
			}
		}
		break;
	case 9:
		//Two Way
		{
			RGBTRIPLE temprgb;
			for(iy=0; iy < cyImage-1; iy++)
			{
				prgbr=prgb+cxImage/2;
				for(ix=0;ix < cxImage/2;ix++,prgb++,prgbr++)
				{
					temprgb=*prgb;
					*prgb=*prgbr;
					*prgbr=temprgb;
				}
				prgb+=cxImage/2;
			}
		}
		break;
	case 10:
		//Fog
		{
			double d;

			d=RAND_MAX/50;
			prgb+=cxImage;
			for (iy=1;iy<cyImage-2; iy++, prgb+=cxImage)
			{
				
				for(ix=2;ix<cxImage;ix++)
				{
					if( rand()< d)
					{
						prgb[ix].rgbtRed = 255;
						prgb[ix].rgbtGreen = 255;
						prgb[ix].rgbtBlue = 255;
					}
				}
				
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		}
		break;
	case 11:
		//Sepia
		{
			BYTE grey;
			for (iy=0; iy < numPixels-2; iy++, prgb++,prgbr--)
			{
				grey = (30*prgb->rgbtRed + 59*prgb->rgbtGreen+11*prgb->rgbtBlue)/100;
				prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) grey;
			}
		}
		break;
	case 12:
		//Distroit
		{
			for (iy=0; iy < numPixels-2; iy++, prgb++,prgbr--)
			{
				prgb->rgbtRed   = (BYTE) (prgb->rgbtRed&prgb->rgbtBlue);
				prgb->rgbtGreen = (BYTE) (prgb->rgbtGreen&prgb->rgbtRed);
				prgb->rgbtBlue  = (BYTE) (prgb->rgbtBlue&prgb->rgbtGreen);
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		}
		break;
	case 13:
		//Line Dedetection
		{
			for (iy=0; iy < numPixels-2; iy++, prgb++,prgbr--)
			{
				prgb->rgbtRed   = (BYTE) ((prgb->rgbtRed)^~((prgb+1)->rgbtRed));
				prgb->rgbtGreen = (BYTE) ((prgb->rgbtGreen)^~((prgb+1)->rgbtGreen));
				prgb->rgbtBlue  = (BYTE) ((prgb->rgbtBlue)^~((prgb+1)->rgbtBlue));
			}
		}
		break;
	case 14:
		//RedPlanet
		{
			for (iy=0; iy < numPixels; iy++, prgb++,prgbr--)
				prgb->rgbtRed   = (BYTE)~prgb->rgbtRed;
		}
		break;
	case 15:
		//Jerk
		{
			RGBTRIPLE temprgb;
			for (iy = 0 ; iy < pvi->bmiHeader.biHeight/1.5; iy+=2) 
			{
				for (ix = 0 ; ix < pvi->bmiHeader.biWidth-5; ix++,prgb++)
				{
				temprgb=*prgb;
				*prgb=*(prgb+5);
				*(prgb+5)=temprgb;
				}
				prgb +=cxImage*2+4;
			}
			
		 }
		break;
	case 16:
		//Thresh Hold
		{
			for (iy=0; iy < numPixels; iy++, prgb++,prgbr--)
			{
				prgb->rgbtBlue  =(prgb->rgbtRed + prgb->rgbtGreen) >> 1;
				prgb->rgbtRed   = (BYTE) ((prgb->rgbtBlue)> 127? 0:255);
				prgb->rgbtGreen = (BYTE) ((prgb->rgbtBlue) > 127? 0:255);
				prgb->rgbtBlue  = (BYTE) ((prgb->rgbtBlue) > 127? 0:255);
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		
		}
		break;
	case 17:
		//up and Down
		{
			RGBTRIPLE temprgb;
			for (iy=0; iy < numPixels/2; iy++, prgb++,prgbr--)
			{
				temprgb=*prgb;
				*prgb=*prgbr;
				*prgbr=temprgb;
			}

		}
		break;
	case 18:
		//Red Channel
		{
			for (iy=0; iy < numPixels; iy++, prgb++) {
				prgb->rgbtGreen = 0;
				prgb->rgbtBlue = 0;
			}
        }
        break;
	case 19:
		//Green Channel
		{
			for (iy=0; iy < numPixels; iy++, prgb++) {
              prgb->rgbtRed = 0;
              prgb->rgbtBlue = 0;
           }
		}
        break;
    case 20:
		//Blue Channel
		{
			for (iy=0; iy < numPixels; iy++, prgb++) {
               prgb->rgbtRed = 0;
               prgb->rgbtGreen = 0;
           }
		}
        break;
   	case 21:
		// Bitwise shift each component to the right by 1
        // this results in the image getting much darker
		{
			for (iy=0; iy < numPixels; iy++, prgb++) {
                prgb->rgbtRed   = (BYTE) (prgb->rgbtRed >> 1);
                prgb->rgbtGreen = (BYTE) (prgb->rgbtGreen >> 1);
                prgb->rgbtBlue  = (BYTE) (prgb->rgbtBlue >> 1);
         }
		}
        break;
    case 22:
		// Toggle each bit - this gives a sort of X-ray effect
		//StrongPostrise
		{
			for (iy=0; iy < numPixels; iy++, prgb++) {
                prgb->rgbtRed   = (BYTE) 255*(1+(prgb->rgbtRed-128));
                prgb->rgbtGreen = (BYTE) 255*(1+(prgb->rgbtGreen-128));
                prgb->rgbtBlue  = (BYTE) 255*(1+(prgb->rgbtBlue-128));
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		}
        break;
     case 23:
		 // Zero out the five LSB per each component
		 //Postrise
		 {
			for (iy=0; iy < numPixels; iy++, prgb++) {
                prgb->rgbtRed   = (BYTE) (prgb->rgbtRed & 0xe0);
                prgb->rgbtGreen = (BYTE) (prgb->rgbtGreen & 0xe0);
                prgb->rgbtBlue  = (BYTE) (prgb->rgbtBlue & 0xe0);
            }
			if(opts)
				Smooth(top,cxImage,cyImage);
		 }
          break;
     case 24:
		 // Take pixel and its neighbor two pixels to the right and average
         // then out - this blurs them and produces a subtle motion effect
		 {
			for (iy = 0 ; iy < pvi->bmiHeader.biHeight; iy++) 
			{
                for (ix = 2 ; ix < pvi->bmiHeader.biWidth; ix++,prgb++) 
				{
                    prgb->rgbtRed   = (BYTE) ((prgb->rgbtRed + prgb[2].rgbtRed) >> 1);
                    prgb->rgbtGreen = (BYTE) ((prgb->rgbtGreen + prgb[2].rgbtGreen) >> 1);
                    prgb->rgbtBlue  = (BYTE) ((prgb->rgbtBlue + prgb[2].rgbtBlue) >> 1);
				}
                prgb +=2;
			}
		 }
		break;
     case 25:
		// Really sleazy emboss - rather than using a nice 3x3 convulution
        // matrix, we compare the greyscale values of two neighbours. If
        // they are not different, then a mid grey (128, 128, 128) is
        // supplied.  Large differences get father away from the mid grey
		 {
			BYTE grey,grey2,temp;
			for (iy = 0 ; iy < pvi->bmiHeader.biHeight; iy++) 
			{
                grey2 = (prgb->rgbtRed + prgb->rgbtGreen+prgb->rgbtGreen) ;
                prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) 255;
                prgb++;
				for (ix = 1 ; ix < pvi->bmiHeader.biWidth; ix++) 
				{
                    grey = (prgb->rgbtRed + prgb->rgbtGreen+prgb->rgbtGreen) ;
                    temp = grey - grey2;
                    if (temp > 127) temp = 255;
                    if (temp < 0) temp = 0;
                    temp += 128;
                    prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) temp;
                    grey2 = grey;
                    prgb++;
				}
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		 }	
        break;
	 case 26:
		 //Double act x
		 {
			RGBTRIPLE temprgb;
			for (iy=0; iy < cyImage-1; iy++)
			{
				prgbr=prgb+cxImage;
				for(ix=0;ix < cxImage/2;ix++,prgb++,prgbr--)
				{
					temprgb=*prgb;
					prgb->rgbtRed=(prgbr->rgbtRed+temprgb.rgbtRed)/2;
					prgb->rgbtGreen=(prgbr->rgbtGreen+temprgb.rgbtGreen)/2;
					prgb->rgbtBlue=(prgbr->rgbtBlue+temprgb.rgbtBlue)/2;
					prgbr->rgbtRed=(temprgb.rgbtRed+prgbr->rgbtRed)/2;
					prgbr->rgbtGreen=(temprgb.rgbtGreen+prgbr->rgbtGreen)/2;
					prgbr->rgbtBlue=(temprgb.rgbtBlue+prgbr->rgbtBlue)/2;
				}
				prgb+=cxImage/2;
			}
		 }
         break;
	 case 27:
		 //Blue Magnet using log
		 {
			 for (iy=0; iy < numPixels; iy++, prgb++) {
                prgb->rgbtRed   = (BYTE) (46*log(abs(prgb->rgbtRed-(prgb->rgbtRed+prgb->rgbtGreen+prgb->rgbtBlue)/2)+1));
                prgb->rgbtGreen = (BYTE) (46*log(abs(prgb->rgbtGreen -(prgb->rgbtRed+prgb->rgbtGreen+prgb->rgbtBlue)/2)+1));
                prgb->rgbtBlue  = (BYTE) (46*log(abs(prgb->rgbtBlue -(prgb->rgbtRed+prgb->rgbtGreen+prgb->rgbtBlue)/2)+1));
			}
		 }
		 break;
	 case 28:
		 //Distrotion
		 {
			for (iy=0; iy < numPixels; iy++, prgb++) {
                				
			  prgb->rgbtBlue=abs(128-prgb->rgbtBlue);
			  prgb->rgbtGreen =abs(128-prgb->rgbtGreen);
			  prgb->rgbtRed =abs(128- prgb->rgbtRed);
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		 }
		 break;
	 case 29:
		 //Grid
		 {
			for (iy=0; iy < cyImage; iy++, prgb++) {
			  for(ix=0;ix<cxImage-1;ix++,prgb++)
			  {
				  if(!(iy%16))
				  {
				  prgb->rgbtBlue=0;
				  prgb->rgbtGreen=0;
				  prgb->rgbtRed=0;
				  }
				  if(!(ix%16))
				  {
				  prgb->rgbtBlue=0;
				  prgb->rgbtGreen=0;
				  prgb->rgbtRed=0;
				  }
			  }
			}
		 }
		 break;
	 case 30:
		 //Shadow
		 {
			for (iy=0; iy < cyImage-10; iy++, prgb+=cxImage) {
			  for(ix=0;ix<cxImage-10;ix++)
			  {
				  prgb[ix].rgbtBlue=(prgb[ix].rgbtBlue+prgb[ix+10].rgbtBlue)/2;
				  prgb[ix].rgbtGreen=(prgb[ix].rgbtGreen+prgb[ix+10].rgbtGreen)/2;
				  prgb[ix].rgbtRed=(prgb[ix].rgbtRed+prgb[ix+10].rgbtRed)/2;
				 
			  }
			}
		 }
		  break;
	 case 31:
		 //Line Art
		 {
			BYTE grey;
			for (iy=0; iy < cyImage; iy++, prgb++) {
			  for(ix=0;ix<cxImage-1;ix++,prgb++)
			  {
				  grey = (30*prgb->rgbtRed + 59*prgb->rgbtGreen+11*prgb->rgbtBlue)/100;
				  if(grey>157)
				  {
					  prgb->rgbtBlue=255;
					  prgb->rgbtGreen=255;
					  prgb->rgbtRed=255;
				  }
				  else
				  {
					  prgb->rgbtBlue=0;
					  prgb->rgbtGreen=0;
					  prgb->rgbtRed=0;
				  }
				 
			  }
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		 }
		 break;
	 case 32:
		 //DeInterlace
		 {
			for (iy=0; iy < cyImage; iy++, prgb++) {
			 
			 if ((iy % 2 == 1) || (iy - 1 < 0) || (iy + 1 >= cyImage))
				for (ix = cxImage;ix; ix--)
					prgb++;
			 else
				for (ix = cxImage-1;ix;ix--) {
					prgb->rgbtRed=((prgb-cxImage)->rgbtRed+(prgb+cxImage)->rgbtRed)>>1;
					prgb->rgbtGreen=((prgb-cxImage)->rgbtGreen+(prgb+cxImage)->rgbtGreen)>>1;
					prgb->rgbtBlue=((prgb-cxImage)->rgbtBlue+(prgb+cxImage)->rgbtBlue)>>1;
					prgb++;
					//*dest++ = (*(src - rowsiz) + *(src + rowsiz)) >> 1;
				}

			}
		 }
		 break;
	 case 33:
		 //DoubleAct in Up an Down
		 {
			RGBTRIPLE temprgb;
			for (iy=0; iy < numPixels/2; iy++, prgb++,prgbr--) {
		  	   	temprgb=*prgb;
				prgb->rgbtRed=(prgbr->rgbtRed+temprgb.rgbtRed)/2;
				prgb->rgbtGreen=(prgbr->rgbtGreen+temprgb.rgbtGreen)/2;
				prgb->rgbtBlue=(prgbr->rgbtBlue+temprgb.rgbtBlue)/2;
				prgbr->rgbtRed=(temprgb.rgbtRed+prgbr->rgbtRed)/2;
				prgbr->rgbtGreen=(temprgb.rgbtGreen+prgbr->rgbtGreen)/2;
				prgbr->rgbtBlue=(temprgb.rgbtBlue+prgbr->rgbtBlue)/2;
		  }
		 }
		 break;
	 case 34:
		//Lake
		 {
			RGBTRIPLE *til,*top;
			top=prgb;
			prgb=prgbr-cxImage;
			til=prgbr;
			for(iy=1;iy<cyImage;iy+=2,prgb-=cxImage)
				memcpy(prgb,til-cxImage*iy,(sizeof(RGBTRIPLE)*cxImage));

			prgb=top;
			for(iy=1;iy<=cyImage/2;iy++,prgb+=cxImage)
				memcpy(prgb,til-cxImage*iy,(sizeof(RGBTRIPLE)*cxImage));
		 }
		break;
	 case 35:
		//tile
		 {		
			RGBTRIPLE *til,*top;
			til=new RGBTRIPLE[cxImage];
			top=prgb;
			for (iy=0;iy<cyImage;iy+=2,prgb+=cxImage)
			{
				memcpy(til,prgb,(sizeof(RGBTRIPLE)*cxImage));
				for(ix=0;ix<cxImage;ix+=2,prgb++)
					*prgb=til[ix];
				for(ix=1;ix<cxImage;ix+=2,prgb++)
					*prgb=til[ix];
				
			}
			delete []til;
			til=NULL;
			prgb=top;
			til=top;
			for(iy=0;iy<cyImage;iy+=2,prgb+=cxImage)
				memcpy(prgb,til+cxImage*iy,(sizeof(RGBTRIPLE)*cxImage));
			prgb=top;
			til=top+(cyImage/2)*cxImage;
			for(iy=cyImage/2;iy<cyImage;iy++,prgb+=cxImage,til+=cxImage)
				memcpy(til,prgb,(sizeof(RGBTRIPLE)*cxImage));
		 }
		break;
	 case 36:
		//4 tile with mirror
		 {
			RGBTRIPLE *til,*top;
			til=new RGBTRIPLE[cxImage];
			top=prgb;
			for (iy=0;iy<cyImage;iy+=2,prgb+=cxImage)
			{
				memcpy(til,prgb,(sizeof(RGBTRIPLE)*cxImage));
				for(ix=0;ix<cxImage;ix+=2,prgb++)
					*prgb=til[ix];
				for(ix=cxImage-1;ix>0;ix-=2,prgb++)
					*prgb=til[ix];
			}
			delete []til;
			til=NULL;
			prgb=prgbr-cxImage;
			til=prgbr;
			for(iy=2;iy<cyImage+1;iy+=2,prgb-=cxImage)
				memcpy(prgb,til-cxImage*iy+1,(sizeof(RGBTRIPLE)*cxImage));
			prgb=top+(cyImage/2)*cxImage;
			til=top+(cyImage/2)*cxImage;
			for(iy=0;iy<cyImage/2;iy++,prgb-=cxImage,til+=cxImage)
				memcpy(prgb,til,(sizeof(RGBTRIPLE)*cxImage));
		}
		break;
	  case 37:
		 //sinmagic
		 {
			 int deg,skip;
			 for(iy=0,deg=0;iy<cyImage;deg+=20,iy++,prgb+=cxImage)
			 {
				if(deg>360)
					 deg=0;
				 skip=(int)(sin((deg*3.14)/360)*10);
				 for(ix=0;ix<cxImage-skip;ix++)
				 	 prgb[ix]=prgb[ix+skip];
			 }
			 if(opts)
				Smooth(top,cxImage,cyImage);
		 }
		 break;
	   case 38:
		  //Smoothing
		  {
			  Smooth(prgb,cxImage,cyImage);		 
		  }
		 break;
	  case 39:
		  //ReduseColor
		  {
			  
			  for(iy=0;iy<numPixels-1;iy++,prgb++)
			  {
				  prgb->rgbtRed&=BYTE(192);
				  prgb->rgbtGreen&=BYTE(192);
				  prgb->rgbtBlue&=BYTE(192);
			  }
			  if(opts)
				Smooth(top,cxImage,cyImage);
		  }
		  break;
	  case 40:
		  //Line art for movie
		   {
			BYTE grey;
			for (iy=0; iy < cyImage; iy++, prgb++) {
			  for(ix=0;ix<cxImage-1;ix++,prgb++)
			  {
				  grey = (30*prgb->rgbtRed + 59*prgb->rgbtGreen+11*prgb->rgbtBlue)/100;
				  if(grey>107)
				  {
					  prgb->rgbtBlue=255;
					  prgb->rgbtGreen=255;
					  prgb->rgbtRed=255;
				  }
				  else
				  {
					  prgb->rgbtBlue=0;
					  prgb->rgbtGreen=0;
					  prgb->rgbtRed=0;
				  }
				 
			  }
			}
			if(opts)
				Smooth(top,cxImage,cyImage);
		 }
		 break;
	  case 41:
		   {
			RGBTRIPLE *til,*top;
			til=new RGBTRIPLE[cxImage];
			top=prgb;
			for (iy=0;iy<cyImage;iy+=2,prgb+=cxImage)
			{
				memcpy(til,prgb,(sizeof(RGBTRIPLE)*cxImage));
				/*for(ix=0;ix<cxImage;ix+=2,prgb++)
					*prgb=til[ix];*/
				for(ix=cxImage;ix>0;ix--,prgb++)
					*prgb=til[ix];
			}
			delete []til;
			til=NULL;
		  }
		  break;
	  case 42:
		  {
			RGBTRIPLE *til,*top;
			til=new RGBTRIPLE[cxImage];
			top=prgb;
			for (iy=0;iy<cyImage;iy++)
			{
				memcpy(til,prgb,(sizeof(RGBTRIPLE)*cxImage));
				for(ix=0;ix<cxImage;ix+=2,prgb++)
					*prgb=til[ix];
				for(ix=cxImage-1;ix>0;ix-=2,prgb++)
					*prgb=til[ix];
			}
			delete []til;
			til=NULL;
		  }
		  break;
	  case 43:
		  {		
			RGBTRIPLE *til,*top;
			til=new RGBTRIPLE[cxImage];
			top=prgb;
			for (iy=0;iy<cyImage;iy++)
			{
				memcpy(til,prgb,(sizeof(RGBTRIPLE)*cxImage));
				for(ix=0;ix<cxImage-1;ix+=2,prgb++)
					*prgb=til[ix];
				for(ix=1;ix<cxImage;ix+=2,prgb++)
					*prgb=til[ix];
				
			}
			delete []til;
			til=NULL;
		  }
	}

	if(eopt)
	{
		if(img)
		{
			img->Process((RGBTRIPLE*)top,cxImage,cyImage);
		}
		
	}
	
	

	
     return NOERROR;
}
HRESULT Filter::NonDelegatingQueryInterface(REFIID riid,void**ppv)
{
	if(riid==IID_ISpecifyPropertyPages)
	{
		return GetInterface((ISpecifyPropertyPages*)this,ppv);
	}
	else if(riid==IID_FilterInterface)
	{
		return GetInterface((IFilterInterface*)this,ppv);
	}
	else
	{
		return CTransInPlaceFilter::NonDelegatingQueryInterface(riid,ppv);
	}
}
STDMETHODIMP Filter::GetPages(CAUUID*pPages)
{
	pPages->cElems=1;
	pPages->pElems=(GUID*)CoTaskMemAlloc(sizeof(GUID));
	if(pPages->pElems==NULL)
	{
		return E_OUTOFMEMORY;
	}
	*(pPages->pElems)=CLSID_FilterPropertyPage;
	return NOERROR;
}

int Filter::Smooth(const RGBTRIPLE *ttop,const int cxImage,const int cyImage)
{
	int ix,iy;
	RGBTRIPLE *top=(RGBTRIPLE*)ttop;

	 for(iy=1;iy<cyImage-2;iy++)
	 {
		  for(ix=1;ix<cxImage-1;ix++)
		  {
			 (top+(cxImage*iy)+ix)->rgbtRed=((top+(cxImage*iy)+ix)->rgbtRed+\
				  (top+(cxImage*(iy-1))+ix-1)->rgbtRed+\
				  (top+(cxImage*(iy-1))+ix)->rgbtRed+\
				  (top+(cxImage*(iy-1))+ix+1)->rgbtRed+\
				  (top+(cxImage*iy)+ix-1)->rgbtRed+\
				  (top+(cxImage*iy)+ix+1)->rgbtRed+\
				  (top+(cxImage*(iy+1))+ix-1)->rgbtRed+\
				  (top+(cxImage*(iy+1))+ix)->rgbtRed+\
				  (top+(cxImage*(iy+1))+ix+1)->rgbtRed)/9;

			  (top+(cxImage*iy)+ix)->rgbtGreen=((top+(cxImage*iy)+ix)->rgbtGreen+\
				  (top+(cxImage*(iy-1))+ix-1)->rgbtGreen+\
				  (top+(cxImage*(iy-1))+ix)->rgbtGreen+\
				  (top+(cxImage*(iy-1))+ix+1)->rgbtGreen+\
				  (top+(cxImage*iy)+ix-1)->rgbtGreen+\
				  (top+(cxImage*iy)+ix+1)->rgbtGreen+\
				  (top+(cxImage*(iy+1))+ix-1)->rgbtGreen+\
				  (top+(cxImage*(iy+1))+ix)->rgbtGreen+\
				  (top+(cxImage*(iy+1))+ix+1)->rgbtGreen)/9;

			  (top+(cxImage*iy)+ix)->rgbtBlue=((top+(cxImage*iy)+ix)->rgbtBlue+\
				  (top+(cxImage*(iy-1))+ix-1)->rgbtBlue+\
				  (top+(cxImage*(iy-1))+ix)->rgbtBlue+\
				  (top+(cxImage*(iy-1))+ix+1)->rgbtBlue+\
				  (top+(cxImage*iy)+ix-1)->rgbtBlue+\
				  (top+(cxImage*iy)+ix+1)->rgbtBlue+\
				  (top+(cxImage*(iy+1))+ix-1)->rgbtBlue+\
				  (top+(cxImage*(iy+1))+ix)->rgbtBlue+\
				  (top+(cxImage*(iy+1))+ix+1)->rgbtBlue)/9;
		  }
	 }

	 return 0;

}

/* Starting code for filter property page*/

BOOL FilterProp::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	char t[50];
	switch(uMsg)
	{
	case WM_CREATE:
	case WM_INITDIALOG:
		SendDlgItemMessage(hwnd,IDC_EDIT2,WM_SETTEXT,0,(LPARAM)"This Filter is Developed For the\
			Kannan's Winamp input plugin.\
			Any other applications are trying to\
			Using this filter without author's\
			Permission is illegal. If any one want\
			this filter contact me:\
				Email Id:\
						kannan_softdev@yahoo.com\
				Phone No:\
						91 4294 222991\
				Address:\
						K.Kannan,\
					S/o K.C.Krishnamoorthy,\
				Palapalayam,\
				Pichandampalayam(PO),\
				Perundurai,\
					Erode(DT),\
					TamilNadu,\
				India-638052.");
		break;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case IDC_BUTTON1:

			SendDlgItemMessage(hwnd,IDC_EDIT1,WM_GETTEXT,50,(LPARAM)t);
			

			if(pIFilterInterface)
			{
				pIFilterInterface->SetOptions(atoi(t));

				//MessageBox(0,t,"90",0);
			}
			break;
		}
		break;
	}
	return FALSE;
}



HRESULT FilterProp::OnConnect(IUnknown *pIUnknown)
{
	if(pIFilterInterface==NULL)
	{
		if(FAILED(pIUnknown->QueryInterface(IID_FilterInterface,(void**)&pIFilterInterface)))
		{
			pIFilterInterface=NULL;
			MessageBox(0,"Interface Connection Error","Error",0);
			return E_NOINTERFACE;
		}
	}

	return NOERROR;
}

HRESULT FilterProp::OnDisconnect()
{

	if(pIFilterInterface)
	{
		pIFilterInterface->Release();
		pIFilterInterface=NULL;
		return NOERROR;
	}
	return E_UNEXPECTED;
}

 //RGB  ==> YIQ

			  //tr=(float)(0.299*prgb->rgbtRed+0.587*prgb->rgbtGreen+0.114*prgb->rgbtBlue);
			  //tg=(float)(0.596*prgb->rgbtRed-0.274*prgb->rgbtGreen+0.322*prgb->rgbtBlue);
			  //tb=(float)(0.212*prgb->rgbtRed-0.523*prgb->rgbtGreen+0.312*prgb->rgbtBlue);

			  //tr+=.9;

		 

			  //YIQ ==> RGB
			  
			  //prgb->rgbtRed=(BYTE)(-1.129*tr+3.306*tg-3.000*tb);
			  //prgb->rgbtGreen=(BYTE)(1.607*tr-0.934*tg+0.386*tb);
			  //prgb->rgbtBlue=(BYTE)(3.458*tr-3.817*tg+5.881*tb);

			 
			  //lum = (current[0] * 0.30) + (current[1] * 0.59) + (current[2] * 0.11);
			  /*tr=prgb->rgbtRed*0.30+prgb->rgbtGreen*0.59+prgb->rgbtBlue*0.11;

			  prgb->rgbtRed=prgb->rgbtRed*tr/255;
			  prgb->rgbtGreen=prgb->rgbtGreen*tr/255;
			  prgb->rgbtBlue=prgb->rgbtBlue*tr/255;
			  */

			   /** Third : home-made...*/
			   /*y = 0.333 * r + 0.333 * g + 0.333 * b;
			   u = r - y;
			   v = g - y;
			   r = y + u;
			   g = y + v;
			   b = y -u -v;
			   */

			 /* tr=0.333*prgb->rgbtRed+0.333*prgb->rgbtGreen+0.333*prgb->rgbtBlue;
			  tg=prgb->rgbtRed-tr;
			  tb=prgb->rgbtGreen-tr;

			  tr+=50;
			  
			  prgb->rgbtRed=tr+tg;
			  prgb->rgbtGreen=tr+tb;
			  prgb->rgbtBlue=tr-tg-tb;
			  */

			  /*

			  pix.Red=prgb->rgbtRed;
			  pix.Green=prgb->rgbtGreen;
			  pix.Blue=prgb->rgbtBlue;

			  //pix.data=pix.data>>1;
			  //pix.Alpha=0;

			  prgb->rgbtRed=pix.Red;
			  prgb->rgbtGreen=pix.Green;
			  prgb->rgbtBlue=pix.Blue;
			  */
/* for(ix=0;ix<cxImage-1;ix++,prgb++)
			  {
				  //lum = (current[0] * 0.30) + (current[1] * 0.59) + (current[2] * 0.11);
				  tr=(BYTE)(prgb->rgbtRed *(float)0.30+prgb->rgbtGreen*(float)0.59+prgb->rgbtBlue*(float)0.11);
				  prgb->rgbtRed=(BYTE)(prgb->rgbtRed *tr)/256;
				  prgb->rgbtGreen=(BYTE)(prgb->rgbtGreen*tr)/256;
				  prgb->rgbtBlue=(BYTE)(prgb->rgbtBlue*tr)/256;
			  }*/


//	 This is for main vision scripts
	//		X=((double)iy/cyImage)*255.0;
	//		Y=((double)ix/cxImage)*255.0;
	//		R=((double)prgb->rgbtRed/255.0);
	//		G=((double)prgb->rgbtGreen/255.0);
	//		B=((double)prgb->rgbtBlue/255.0);






